package org.radsimplified.genapp;

import org.radsimplified.genapp.metadata.App;
import org.radsimplified.genapp.metadata.BizEntity;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import org.apache.velocity.VelocityContext;

public class AppGenerator {

	private static void mkdir(String path) {
		new File(path).mkdirs();
	}
	
	private static void generateCode(String codeFilePath, String templateName, VelocityContext appData, boolean overwrite) throws IOException {
		if (!overwrite) {
			File file = new File(codeFilePath);
			if (file.exists())
				return;
		}
		FileWriter codeFile = new FileWriter(codeFilePath);
		String code = VelocityUtil.mergeTemplateIntoString("codeFiles/" + templateName, appData);
		codeFile.write(code);
		codeFile.close();
	}
	
	public static void generateApp() throws IOException {
		
		App app = App.getApp();

		String[] entityCodeTypes = {"", "Controller", "Service", "ServiceImpl"};
		
		String gcPath =  GenApp.properties.getProperty("codePath"); // "/home/" + GenApp.user + "/workspace/";
		String rootPath =  gcPath + app.getArtifactId() + "/";
		String packagePath = rootPath + "src/main/java/" + app.getGroupId().replace('.', '/') + "/" + app.getArtifactId() + "/";
		
		File rootDir = new File(gcPath + app.getArtifactId());

		if (!rootDir.exists()) {
			
			FileUtil.copy(GenApp.properties.getProperty("skeleton"), gcPath + app.getArtifactId());
			mkdir(packagePath + "generated/common");
			mkdir(packagePath + "generated/converters");
			mkdir(packagePath + "common");
			for (String module: app.getModules()) {
				mkdir(packagePath + "generated/" + module);
				mkdir(packagePath + "handcrafted/" + module);
				mkdir(packagePath + module);
				mkdir(rootPath + "src/main/webapp/WEB-INF/views/" + module);
			}
		}

		VelocityContext appData = new VelocityContext();
		appData.put("app", app);
		appData.put("helper", new Helper());
		appData.put("userEntity", app.getEntity("User"));
		appData.put("dolCurly", "${");

		generateCode(rootPath + "pom.xml", "pom.xml.vm", appData, false);
		generateCode(rootPath + "src/main/resources/app.properties", "app.properties.vm", appData, true);
		generateCode(rootPath + "src/main/webapp/WEB-INF/messages/messagesGenerated.properties", "messagesGenerated.properties.vm", appData, true);
		generateCode(rootPath + "src/main/webapp/WEB-INF/spring/app-config.xml", "app-config.xml.vm", appData, true);
		generateCode(rootPath + "src/main/webapp/WEB-INF/spring/mail.xml", "mail.xml.vm", appData, true);
		generateCode(packagePath + "generated/common/Ref.java", "Ref.java.vm", appData, true);
		generateCode(packagePath + "generated/common/PageInfo.java", "PageInfo.java.vm", appData, true);
		generateCode(packagePath + "generated/common/Paginate.java", "Paginate.java.vm", appData, true);
		generateCode(packagePath + "generated/common/SelectOption.java", "SelectOption.java.vm", appData, true);
		generateCode(packagePath + "generated/common/SmtpAuthenticator.java", "SmtpAuthenticator.java.vm", appData, true);
		generateCode(packagePath + "generated/common/HelperGenerated.java", "HelperGenerated.java.vm", appData, true);
		generateCode(packagePath + "common/Helper.java", "Helper.java.vm", appData, false);
		generateCode(packagePath + "generated/common/CaptchaController.java", "CaptchaController.java.vm", appData, true);
		generateCode(packagePath + "generated/common/BaseControllerGenerated.java", "BaseControllerGenerated.java.vm", appData, true);
		generateCode(packagePath + "common/BaseController.java", "BaseController.java.vm", appData, true);
		generateCode(packagePath + "generated/common/RootControllerGenerated.java", "RootControllerGenerated.java.vm", appData, true);
		generateCode(packagePath + "common/RootController.java", "RootController.java.vm", appData, false);
		generateCode(packagePath + "generated/ChangePasswordForm.java", "ChangePasswordForm.java.vm", appData, true);
		generateCode(packagePath + "generated/ForgotPasswordForm.java", "ForgotPasswordForm.java.vm", appData, true);
		generateCode(packagePath + "generated/common/BaseEntityGenerated.java", "BaseEntityGenerated.java.vm", appData, true);
		generateCode(packagePath + "common/BaseEntity.java", "BaseEntity.java.vm", appData, false);
		generateCode(packagePath + "generated/common/BaseServiceGenerated.java", "BaseServiceGenerated.java.vm", appData, true);
		generateCode(packagePath + "generated/common/BaseServiceImplGenerated.java", "BaseServiceImplGenerated.java.vm", appData, true);
		generateCode(packagePath + "common/BaseService.java", "BaseService.java.vm", appData, true);
		generateCode(packagePath + "common/BaseServiceImpl.java", "BaseServiceImpl.java.vm", appData, true);
		generateCode(rootPath + "src/main/webapp/WEB-INF/views/register.jsp", "register.jsp.vm", appData, true);

		for (BizEntity entity: app.getEntities()) {
			
			appData.put("entity", entity);
			
			for (String codeType: entityCodeTypes) {
				generateCode(packagePath + "generated/" + entity.getModuleUrl() + "/" +
						entity.getName() + codeType + "Generated.java", "Entity" + codeType + "Generated.java.vm", appData, true);
				generateCode(packagePath + "handcrafted/" + entity.getModuleUrl() + "/" +
						entity.getName() + codeType + "Handcrafted.java", "Entity" + codeType + "Handcrafted.java.vm", appData, false);
				generateCode(packagePath + entity.getModuleUrl() + "/" +
						entity.getName() + codeType + ".java", "Entity" + codeType + ".java.vm", appData, false);
			}

			generateCode(packagePath + "generated/converters/StringTo" +
					entity.getName() + ".java", "StringToEntity.java.vm", appData, true);
			generateCode(packagePath + "generated/" + entity.getModuleUrl() + "/" +
					entity.getName() + "SearchForm.java", "EntitySearchForm.java.vm", appData, true);
			generateCode(rootPath + "src/main/webapp/WEB-INF/views/" + entity.getModuleUrl() + "/" +
					entity.getCamelName() + ".jsp", "entity.jsp.vm", appData, true);
			generateCode(rootPath + "src/main/webapp/WEB-INF/views/" + entity.getModuleUrl() + "/" +
					entity.getCamelName() + "Edit.jsp", "entityEdit.jsp.vm", appData, true);
			generateCode(rootPath + "src/main/webapp/WEB-INF/views/" + entity.getModuleUrl() + "/" +
					entity.getPlural() + ".jsp", "entities.jsp.vm", appData, true);
		}
	}
	
}
